package lk.icta.core.dao.impl;

import lk.icta.common.AppConstants;
import lk.icta.common.dao.PreloadableDAO;
import lk.icta.common.dao.impl.BaseDAO;
import lk.icta.core.dao.LandUsageDAO;
import lk.icta.core.entity.LandUsage;
import lk.icta.common.ErrorCodes;
import lk.icta.user.entity.User;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.*;

/**
 * @author Duminda Dharmakeerthi
 */
public class LandUsageDAOImpl extends BaseDAO implements LandUsageDAO, PreloadableDAO {

    private final Map<Integer, String> siNames = new HashMap<Integer, String>();
    private final Map<Integer, String> enNames = new HashMap<Integer, String>();
    private final Map<Integer, String> taNames = new HashMap<Integer, String>();

    @Transactional(propagation = Propagation.MANDATORY)
    public void addLandUsage(LandUsage landUsage, User user) {
        logger.debug("Add a land usage [Usage Name: {}]", landUsage.getEnUsageName());
        em.persist(landUsage);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void updateLandUsage(LandUsage landUsage, User user) {
        logger.debug("Update a land usage [Usage Name: {}]", landUsage.getEnUsageName());
        em.merge(landUsage);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public LandUsage getLandUsageById(int id, User user) {
        logger.debug("Loading land usage [Usage id: {}]", id);
        return em.find(LandUsage.class, id);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public List<LandUsage> getAllLandUsages() {
        logger.debug("List all land usages");
        Query q = em.createNamedQuery("getAllLandUsages");
        return q.getResultList();
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public Map<Integer, String> getAllLandUsages(String language, User user) {
        logger.debug("Listing land usages in {}", language);
        Map<Integer, String> result = null;
        if (AppConstants.SINHALA.equals(language)) {
            result = siNames;
        } else if (AppConstants.ENGLISH.equals(language)) {
            result = enNames;
        } else if (AppConstants.TAMIL.equals(language)) {
            result = taNames;
        } else {
            handleException("Unsupported language : " + language, ErrorCodes.INVALID_LANGUAGE);
        }
        if (result != null)
            return result;
        else
            return Collections.emptyMap();
    }

    @Override
    public Map<Integer, String> getAllLandUsageTypesByUserLanguage(String language, User user) {
        logger.debug("Listing Land Usage Types in {} by {}", language, user.getUsername());
        Query q = em.createNamedQuery("getAllLandUsages");
        List<LandUsage> landUsageList = q.getResultList();
        for (LandUsage landUsage : landUsageList) {
            siNames.put(landUsage.getId(), landUsage.getSiUsageName());
            enNames.put(landUsage.getId(), landUsage.getEnUsageName());
            taNames.put(landUsage.getId(), landUsage.getTaUsageName());
        }
        if (AppConstants.SINHALA.equals(language)) {
            return siNames;
        } else if (AppConstants.ENGLISH.equals(language)) {
            return enNames;
        } else if (AppConstants.TAMIL.equals(language)) {
            return taNames;
        } else {
            handleException("Unsupported language : " + language, ErrorCodes.INVALID_LANGUAGE);
        }
        return Collections.emptyMap();
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public void preload() {
        Query query = em.createQuery("SELECT l FROM LandUsage l");
        List<LandUsage> results = query.getResultList();
        for (LandUsage l : results) {
            siNames.put(l.getId(), l.getSiUsageName());
            enNames.put(l.getId(), l.getEnUsageName());
            taNames.put(l.getId(), l.getTaUsageName());
        }
    }
}
